﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IWMAG.Scripting.AST.ObjectModel;
using IWMAG.Scripting.Types;
using IWMAG.Scripting.Compiler;
using IWMAG.Scripting.Interpreter;
using IWMAG.Scripting.Compiler.UserInfo;

namespace IWMAG.Scripting.AST.TerminalExpressions {
    internal class ArrayExpression : CodeExpression {
        public List<CodeExpression> Elements = new List<CodeExpression>();

        public ArrayExpression(Lexeme l) : base(l) { }

        public override void Verify(Helpers.CompileTable sym, List<Compiler.IUserInfo> error) {
            CodeType t = null;
            foreach (CodeExpression expr in Elements) {
                expr.Verify(sym, error);

                if (t == null) {
                    t = expr.TypeOf();
                } else {
                    if (!t.Equals(expr.TypeOf())) {
                        SendError(error, Rules.AllMembersOfConstantArrayExpressionMustBeOfCompatibleTypes, t.ToString());
                    }
                }
            }
        }


        public override CodeType TypeOf() {
            if (Elements.Count == 0) {
                return new ArrayType(CodeType.Void);
            }
            return new ArrayType(Elements[0].TypeOf());
        }

        public override IEnumerable<Continuation> ValueOf(Interpreter.ScriptEngine engine, Helpers.RuntimeTable sym, Interpreter.Reference<Interpreter.RunValue> val) {
            ArrayRunValue array = new ArrayRunValue();

            foreach (CodeExpression expr in Elements) {
                Reference<RunValue> value = RunValue.NoValue;
                foreach (Continuation wait in expr.ValueOf(engine, sym, value)) yield return wait;
                array.Add(new RunValue(value.ReferencedValue.Value));
            }

            val.ReferencedValue.Value = array;
        }
    }
}
